package com.game.logic.fighting.skill.skill;


import com.coment.cfg.luban.RolesSkillCfg;
import com.coment.cfg.luban.Tables;
import com.coment.cfg.luban.constant.AIDCFG;
import com.coment.cfg.luban.gift.GiftEffectCfg;
import com.coment.message.HurtInfo;
import com.coment.po.Game;
import com.coment.po.roles.Roles;
import com.game.dao.core.GameDao;
import com.game.dao.user.roles.RolesDao;
import com.game.framework.lock.LooksManager;
import com.game.framework.lock.annotation.WriteLock;
import com.game.logic.fighting.actor.SkillInfo;
import com.game.logic.fighting.attrs.FightingLogic;
import com.xs.build.server.websocket.channel.ClientManager;
import jakarta.annotation.Resource;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.experimental.FieldDefaults;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Optional;
import java.util.concurrent.locks.ReentrantLock;

/// 礼物技能事件
@Slf4j
@Component
public class GiftSkillsEventHandler {
    @Resource
    private RolesDao rolesDao;
    @Resource
    private GameDao gameDao;

    /// 尝试使用礼物技能
    @EventListener(classes = GiftSkillsEvent.class)
    public void tryUseSkill(GiftSkillsEvent event) {
        Integer anchorInfoId  = event.getAnchorInfoId();
        Integer userInfoId  = event.getUserInfoId();
        String giftId  = event.getGiftId();
        int giftCount = event.getGiftCount();
        ReentrantLock lock = LooksManager.actionLocks.computeIfAbsent(anchorInfoId.toString(), k -> new ReentrantLock());

        lock.lock();
        try {
            Game game = gameDao.findByIdMust(anchorInfoId);

            GiftEffectCfg giftEffectCfg = Tables.cfg.get_tbgifteffectcfg().get(giftId);
            int skillId = giftEffectCfg.skillId;
            int lv = giftEffectCfg.lv;
            RolesSkillCfg rolesSkillCfg = Tables.cfg.get_tbrolesskillcfg().get(skillId * 1000 + lv);

            if (Optional.ofNullable(rolesSkillCfg).isEmpty()) {
                return;
            }
            if (rolesSkillCfg.damage == null) {
                return;
            }
            if (rolesSkillCfg.damage.hurtType != 4) {
                return;
            }


            Double hurtValue = rolesSkillCfg.damage.percentValue.get(0);
            // 秒杀?
            boolean seckill = rolesSkillCfg.damage.percentValue.get(1) == 1;

            SkillInfo skillInfo = new SkillInfo(anchorInfoId, userInfoId, skillId);

            for (int i = 0; i < giftCount; i++) {
                List<HurtInfo> hurtInfos = game.monsterSet.stream().map(monsterId -> doHurt(
                        monsterId, seckill, hurtValue
                )).toList();
                skillInfo.hurts.addAll(hurtInfos);

                ClientManager.sendMessageToClient(anchorInfoId, skillInfo);
            }
        } finally {
            lock.unlock();
        }
    }

    @WriteLock(writeclass = Roles.class, parameterIndex = "#monsterId")
    private HurtInfo doHurt(String monsterId, boolean seckill, Double hurtValue) {
        HurtInfo hurtInfo = new HurtInfo();
        hurtInfo.setRolesId(monsterId);
        Roles monster = rolesDao.findByIdMust(monsterId);
        if (seckill && monster.cardId < 3000) {
            hurtInfo.setDead(true);
            monster.rolePanel.cultivatePanel.base.put(AIDCFG.hp, 0D);
            rolesDao.save(monster);
        } else {
            hurtInfo.setHurt(hurtValue);
            FightingLogic.beHarmed(monster, hurtValue);
            hurtInfo.setHp(monster.rolePanel.getAttribute().get(AIDCFG.hp));
            rolesDao.save(monster);
        }
        return hurtInfo;
    }


    @Getter
    @FieldDefaults(level = AccessLevel.PUBLIC)
    public static class GiftSkillsEvent extends ApplicationEvent {
        public Integer anchorInfoId;
        Integer userInfoId;
        String giftId;
        int giftCount;

        public GiftSkillsEvent(Object source, Integer anchorInfoId, Integer id, String giftId, int giftCount) {
            super(source);
            this.anchorInfoId = anchorInfoId;
            this.userInfoId = id;
            this.giftId = giftId;
            this.giftCount = giftCount;
        }
    }
}
